package p12_jdk代理原理;

import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;

/**
 * 这里模拟了JDK生成的代理类，不过这里的代理类是写死的
 * 而JDK生成代理类是在运行时使用字节码技术ASM动态生成的
 * 有兴趣可以去了解下ASM如何生成代理类
 */
public class $Proxy0 implements Foo {
    InvocationHandler invocationHandler;
    public $Proxy0(InvocationHandler invocationHandler) {
        this.invocationHandler = invocationHandler;
    }

    /**
     * 这里定义了方法对象(方法来自目标类)，这里为了模拟简单，方法对象是写死的
     * 运行时会分析接口方法的签名，返回值，然后生成几个方法对象的静态变量，以及实现类的代码
     */
    static Method foo;
    static Method bar;
    static {
        try {
            foo = Foo.class.getMethod("foo");
            bar = Foo.class.getMethod("bar");
        } catch (NoSuchMethodException e) {
            throw new NoSuchMethodError(e.getMessage());
        }
    }

    @Override
    public void foo() {
        try {
            //回调调用方定义的方法
            invocationHandler.invoke(this, foo, new Object[0]);
        } catch (RuntimeException | Error e) {
            throw e;
        } catch (Throwable e) {
            //将编译时异常变成运行时异常
            throw new UndeclaredThrowableException(e);
        }
    }

    @Override
    public long bar() {
        try {
            Object result = invocationHandler.invoke(this, bar, new Object[0]);
            return (long)result;
        } catch (RuntimeException | Error e) {
            throw e;
        } catch (Throwable e) {
            throw new UndeclaredThrowableException(e);
        }
    }
}
